home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
rdcf.exe
/
RDCF2.DOC
< prev
next >
Wrap
Text File
|
1993-01-15
|
72KB
|
1,680 lines
RDCF: A Reentrant DOS-Compatible File System, Version 2.0
by Philip J. Erdelsky
PLAIN VANILLA CORPORATION
CompuServe 75746,3411
InterNet 75746.3411@compuserve.com
January 15, 1993
Copyright (c) 1993 Plain Vanilla Corporation
1. Introduction
---------------
RDCF is a reentrant and ROMable DOS-compatible file system designed for use
with floppy diskettes and hard disk partitions that do not exceed 32 Mbytes in
size.
For users who are familiar with version 1.0, here is a summary of the
differences between versions 1.0 and 2.0:
(1) Version 2.0 supports subdirectories and volume names. This is by far
the most important difference.
(2) Version 2.0 can be compiled to adapt to different sector sizes at run
time.
(3) Version 2.0 has no default drive option, but it can be compiled with or
without multiple drive support.
(4) The parameters to some functions have been changed slightly to make them
more uniform.
(5) Version 2.0 requires access to the system clock, although a dummy access
function will suffice for systems without clocks.
(6) In version 2.0, the drive access function pointer is stored in the file
control block by the calling program, instead of being passed as a
parameter.
(7) In version 2.0, direct access to the file control block is not encouraged
to the extent it was in version 1.0.
(8) Version 2.0 has a few additional features, such as a directory sort
function, that were not in version 1.0 and are not in most
implementations of DOS.
(9) Version 2.0 is copyrighted. Although you may use it non-commercially
without registering it or paying any fees, resale or commercial use
requires permission and payment of a one-time royalty.
Although DOS 3 permits characters from the IBM extended character set in file
names, most DOS applications don't, and neither does RDCF.
Since DOS 1 is now obsolete, RDCF does not support DOS 1 diskette formats.
RDCF is fully reentrant with respect to files on different drives. It is also
reentrant with respect to files on the same drive, provided they are opened for
reading only. It is not reentrant with respect to different files on the same
drive, if any of them are being written. Therefore, access to it in this case
must be serialized on a drive-by-drive basis when it is used in a multitasking
system.
RDCF does not call on the memory allocator. All working storage for an open
file is contained in a file control block and a scratch buffer that you must
allocate in some manner before calling on RDCF. In a manner of speaking, this
is a reversion to the old CP/M standard, but it permits complete reentrancy
and does not limit the number of open files.
Since RDCF treats each open file as though it were the only open file, it
cannot detect collisions. For example, in a multitasking system, if a file is
written by two tasks at the same time, it will be corrupted. The disk may end
up with lost clusters and cross-linked chains, but other files on the same disk
should keep their integrity.
RDCF requires access to a real-time clock. If your system does not have a
real-time clock, you can write a dummy clock interface that always returns some
standard date and time, such as the notorious 1/1/80 00:00:00, which will be
applied whenever a file is created or modified.
RDCF accesses a disk one sector at a time. While this may seem appallingly
inefficient, it appears adequate in some cases where only minimal file
operations are required. A simple cache system, which is also available from
the same source, will improve its efficiency in other cases. With simple
interfaces and full source code, you can make other changes that you deem
necessary for your own application.
RDCF can be compiled as a read-only file system. This eliminates much of the
code and is suitable for devices that load operating code and other data from
DOS diskettes but do not write anything on them.
RDCF can be compiled to handle multiple drives, in which case every file
specification must begin with a drive letter (followed by a colon). If your
system has only one drive, or if you prefer to handle drive selection outside
RDCF, you can compile RDCF without multiple drives, in which case a file
specification must NOT begin with a drive letter.
The interface to RDCF is not ANSI-compliant, although you could put an ANSI
compliant interface on top of it.
2. Compilation Instructions
---------------------------
The source code for RDCF 2.0 consists of the files RDCF2.C and RDCF2.H. The
header file RDCF2.H should be #included in any source file that calls on the
RDCF, because it contains function prototypes and other necessary definitions.
Since a DOS diskette contains a number of fields of specific sizes, your C
compiler must have types of the same sizes. Here is what is required:
type number of bits
----- --------------
char 8
short 16
long 32
int at least 16
If your application is to run on a CPU with "big endian" byte ordering, such as
one of the Motorola 68000 series, RDCF will have to do some byte swapping
because DOS diskettes contain fields with "little endian" ordering. You can do
this by #defining the variable _BIG_ENDIAN.
If you do not need to write anything on disk, you can save a great deal of code
by #defining the variable RDCF_SYSTEM_READ_ONLY. This eliminates almost all
code devoted to writing.
If you system has multiple drives, you can #define the variable
RDCF_MULTIPLE_DRIVES. In this case RDCF will require each file specification
to begin with a drive letter (followed by a colon), and it will pass the drive
number to the drive interface.
If your application has only one drive, or if it has more than one drive but
you want to handle drive selection outside RDCF, leave the variable
RDCF_MULTIPLE_DRIVES undefined. In this case a file specification passed to
RDCF must NOT begin with a drive letter.
All DOS diskettes (and nearly all DOS hard disks) use 512-byte sectors, so the
following definition is included in the header file RDCF2.H:
#define RDCF_SECTOR_SIZE 512
If you change this value, RDCF won't be compatible with DOS, but it can operate
in a consistent manner on disks that it has formatted.
If you leave RDCF_SECTOR_SIZE undefined, then RDCF will read the sector size
from the bootstrap sector of each disk. This produces less efficient code,
because expressions involving the sector size cannot be evaluated at compile
time. However, it enables RDCF to adapt itself to different sector sizes at
run time.
You can cut out the code for any RDCF function that you don't need. The
publicly defined functions in RDCF2.C do not call each other, so one or more
may be removed without difficulty. For example, if you do only sequential file
access, you can cut out the function rdcf_seek(). In fact, RDCF probably has
more functions than most applications require.
RDCF calls on the following standard C functions and macros, which are widely
available and are usually reentrant:
isalpha() longjmp() memcmp() memcpy() memset() setjmp() toupper()
RDCF presumes that all file specifications are expressed in ASCII and that the
C compiler uses ASCII for characters and strings.
To prevent identifier conflicts, all publicly defined RDCF labels begin with
the characters "RDCF", "_RDCF" or "rdcf".
The following public domain packages are usually distributed along with RDCF
2.0:
package files
--------- -----------------------------
CACHE 1.1 CACHE.C, CACHE.DOC, CACHE.H
FILES FILES.C, FILES.COM, FILES.DOC
The FILES package contains examples of the use of RDCF. It is also a rather
handy diskette utility.
3. Drive Access
---------------
RDCF does not read or write disks directly. You must supply it with a pointer
to a function that you have written or adapted for this purpose. RDCF then
calls this function whenever it needs to read or write a disk sector. The
format of the function call is as follows:
e = (*drive_access)(write, drive, LSN, buffer);
int write; nonzero (true) for a write operation; zero (false)
for a read operation
unsigned drive; drive (0=A, 1=B, etc)
unsigned LSN; logical sector number
void *buffer; memory buffer for data
unsigned e; 0 for a successful read or write, or an
implementation-defined nonzero error code
The function is called to read or write only one sector at a time. However,
you may want to implement some kind of read-ahead, caching or delayed writing
at a lower level to improve efficiency.
The function may be required to convert the LSN into side, track and sector
numbers, although many disk controllers will make the conversion internally.
The layout of LSN's is fairly standard, and is designed to minimize head
motion when LSN's are accessed in ascending numerical order. On DOS systems,
the conversion is made as follows:
sector number = LSN % (number of sectors per track) + 1
side number = (LSN / (number of sectors per track)) % (number of sides)
track number = LSN / ((number of sectors per track) * (number of sides))
The sector size, the number of sectors per track and the number of sides are
written into the following bytes of LSN 0 (where byte 0 is the first byte):
byte contents
---- --------------------------------------
11 LS byte of number of bytes per sector
12 MS byte of number of bytes per sector
24 LS byte of number of sectors per track
25 MS byte of number of sectors per track
26 LS byte of number of sides
27 MS byte of number of sides
If RDCF is to adapt automatically to diskettes of different formats in the same
drive, the function (*drive_access)() can simply record these values whenever
LSN 0 is read or written and then use them to find other sectors. Notice that
LSN 0 is always sector 1 of track 0 on side 0.
An error code must be a 16-bit nonzero unsigned value. Its format is
implementation-dependent. When RDCF receives a nonzero return value from the
function (*drive_access)(), it aborts the current operation, puts the return
value into the file control block member called "drive_error" and returns the
error code RDCF_DRIVE_ERROR.
Error correction and retries, if any, must be implemented at a lower level.
If RDCF is used in a reentrant fashion, the function (*drive_access)() must
also have the required reentrancy.
Here is a drive access function that can be used with Turbo C 2.0 (or a
compatible later version of Borland or Turbo C++) under DOS:
#include <dos.h>
unsigned drive_access(int write, unsigned drive, unsigned LSN,
void *buffer)
{
_SI; _DI;
return write ? abswrite(drive, 1, LSN, buffer) :
absread(drive, 1, LSN, buffer);
}
The strange-looking first line of the function goads the compiler into saving
and restoring the SI and DI registers, something that absread() and abswrite()
should do but don't always do, especially when a drive error is detected.
DOS does a little bit of caching when you access disks in this manner.
Therefore, you should call bdos(13,0,0) to flush the buffers before returning
control to DOS. Otherwise DOS may not recognize the changes RDCF has made.
4. Real Time Clock Access
-------------------------
When RDCF needs the date and time, it calls a function as follows:
rdcf_get_date_and_time(p);
struct rdcf_date_and_time *p; pointer to structure to receive
date and time
You must write a version of rdcf_date_and_time() for your own system. If your
system has no real-time clock, the following function will supply the notorious
1-1-80 00:00:00 as the current date and time:
struct rdcf_date_and_time(struct rdcf_date_and_time *p)
{
static struct rdcf_date_and_time DT = {0,0,0,1,1,1980};
memcpy(p, &DT, sizeof(DT));
}
If you run RDCF under DOS and use Turbo C 2.0 (or a compatible later version of
Turbo or Borland C++), the following function will supply the date and time
taken from the system clock:
void rdcf_get_date_and_time(struct rdcf_date_and_time *p)
{
struct date d;
struct time t;
int day;
getdate(&d);
day = d.da_day;
gettime(&t);
getdate(&d);
if (day != d.da_day) gettime(&t);
p->month = d.da_mon;
p->day = d.da_day;
p->year = d.da_year;
p->hour = t.ti_hour;
p->minute = t.ti_min;
p->second = t.ti_sec;
}
Notice that it is sometimes necessary to read the date and time twice to be
sure of getting a consistent reading when the function is called at midnight.
DOS files always have dates in the period 1980-2107.
5. The File Control Block
-------------------------
All working storage for an open file is contained in a file control block of
type "struct rdcf", which is defined in the header file RDCF2.H, and a scratch
buffer described below. You must allocate space for file control blocks and
scratch buffers before calling on RDCF, since RDCF itself does not call on the
memory allocator.
The first element of a file control block is a pointer to a scratch buffer
with room for RDCF_SECTOR_SIZE unsigned characters. The second element is a
pointer to the drive access function defined above. You must initialize these
pointers, perhaps as follows:
static unsigned char my_buffer[RDCF_SECTOR_SIZE];
static struct rdcf f = {my_buffer, drive_access};
If your implementation has a memory allocator, you can use that instead:
struct rcdf f;
f.buffer = malloc(RDCF_SECTOR_SIZE);
f.drive_access = drive_access;
If you leave RDCF_SECTOR_SIZE undefined because your system uses different
sector sizes on different disks, the buffer must be large enough to hold the
largest sector.
If RDCF_MULTIPLE_DRIVES is undefined, but your system has more than one drive,
you must also put the appropriate drive number into the member f.drive so that
it can be passed to the drive access function.
With one exception involving the function rdcf_next_file_information(), neither
the scratch buffer contents nor the scratch buffer pointer needs to be
maintained from one call on RDCF to the next. However, if RDCF is to be used
in a multitasking system, tasks that can call RDCF in a reentrant fashion must
use different scratch buffers. In most cases, it is sufficient to allocate one
scratch buffer for each drive, and to serialize calls on RDCF for each drive.
The drive access function pointer must not be changed while the file
corresponding to the file control block is open.
You don't have to perform any other initialization on your file control
blocks; RDCF does that for you.
The file control block for a successfully opened file contains a number of
members that you can (safely) read and/or write directly, without calling on
RDCF:
member permitted
access meaning
--------------- ---------- ----------------------------------------
buffer read/write pointer to scratch buffer
drive_access read/write pointer to drive access function
drive read/write drive (0=A, 1=B, etc.)
file read file information block, described below
position read file pointer
drive_error read error when RDCF_DRIVE_ERROR is returned
result read result returned by most recent operation
Of course, you should write into the "drive" member only if you have left
RDCF_MULTIPLE_DRIVES undefined but your system has more than one drive.
The file information block is described more fully in Section 6 below.
File control blocks of the same format are also used by some RDCF functions for
working storage, although nothing more than result codes are returned in them.
6. The File Information Block
-----------------------------
The "file" member of a file control block, when filled by RDCF, contains the
following information about a file:
member meaning
--------- ---------------------------------------------------
spec[13] name and extension in ASCII, terminated by \0
attribute DOS file attribute byte (see below)
date_and_time file date and time
first_cluster number of first cluster
size file length in bytes (0 for volume or subdirectory)
The name and extension are at most eight and three characters long,
respectively, they are separated by a period (.) if the extension is
non-blank, and they are terminated by a nul (\0). RDCF always converts small
letters in file names and extensions to the corresponding capital letters
before putting them into the file information block.
If the information block represents a volume name, however, then the spec[]
member contains the name, which is eleven characters long and may contain
small letters and special characters.
The date_and_time member is itself a structure with the following members:
member meaning range
------ --------- -----------------
second file time 0-58, always even
minute file time 0-59
hour file time 0-23
day file date 1-31
month file date 1-12
year file date 1980-2107
The bits of the attribute byte are represented by mnemonics defined in RDCF2.H:
#define RDCF_READ_ONLY 0x01
#define RDCF_HIDDEN 0x02
#define RDCF_SYSTEM 0x04
#define RDCF_VOLUME 0x08
#define RDCF_DIRECTORY 0x10
#define RDCF_ARCHIVE 0x20
The file information and date-and-time blocks also appear outside the file
control block in some contexts.
7. RDCF File Specifications
---------------------------
A file specification under RDCF is almost the same as its DOS counterpart.
As in DOS, case is not significant in file specifications. Moreover, every
name is truncated to eight characters, and every extension is truncated to
three characters. Hence "A:MYPROGRAM.PASCAL", "A:MYPROGRA.PAS", and
"a:myprogra.pas" all represent the same file.
In a multiple-drive system, the file specification MUST begin with a drive
specification (a drive letter followed by a colon). In systems with only one
drive, the file specification must NOT begin with a drive letter. If you want
to handle drive selection outside RDCF, adjust the drive access pointer and
the drive number in the file control block to select the desired drive, and
then remove the drive letter and colon from the file specification before
calling on RDCF.
Since there is no "current directory", the file specification must begin at the
root and contain the names of all intermediate subdirectories. The backslash
at the beginning of the directory path is superfluous and is NOT used. Hence
a file specification such as "C:\UTIL\CHKDSK.COM", which is quite familiar
under DOS, is invalid under RDCF. The RDCF specification is
"C:UTIL\CHKDSK.COM".
For the same reason, RDCF does not permit the special subdirectories "." and
".." in a directory path, but to maintain disk-level compatibility with DOS, it
puts them into subdirectories that it creates.
A directory specification is the same as a file specification, except that it
refers to a subdirectory.
Where required, a root directory is represented by a drive specification alone;
e.g., "B:" represents the root directory on drive B:. In single-drive systems,
the empty string "" represents the root directory.
RDCF treats all file and drive specifications supplied to it as read-only
strings. They may reside in ROM.
8. The Program Interface
------------------------
The RDCF program interface consists of the following functions:
function description
--------------------------- -------------------------------------
rdcf_attribute() change a file attribute
rdcf_close() close a file
rdcf_date_and_time() change a file, volume or subdirectory
date and time
rdcf_delete() delete a file, volume name or
subdirectory
rdcf_directory() create a subdirectory
rdcf_format() format a disk
rdcf_free_space() get disk free space
rdcf_get_file_information() get a directory entry
rdcf_get_volume() get volume name
rdcf_match() match name and extension
rdcf_move() move a file or subdirectory
rdcf_next_file_information() get next directory entry
rdcf_open() open a file
rdcf_read() read from a file
rdcf_recover() recover erased data
rdcf_rename() rename a file or directory
rdcf_seek() move a file pointer
rdcf_set_file_information() write into a directory entry
rdcf_set_volume() write volume name
rdcf_sort_directory() sort a directory
rdcf_undelete() restore a deleted file
rdcf_wipe_drive() wipe out erased data
rdcf_write() write into a file
There are also four externally defined variables, which for reentrancy must be
considered read-only:
rdcf_format_360 rdcf_format_1200
rdcf_format_720 rdcf_format_1440
8.1. rdcf_attribute() - Change a File Attribute
-----------------------------------------------
The following function call changes a file's attribute byte:
e = rdcf_attribute(fcb, filespec, attribute);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
unsigned attribute; new attribute byte
int e; 0 if file was successfully modified,
or negative error code
Only the following attribute bits are affected by this function:
RDCF_ARCHIVE RDCF_READ_ONLY
RDCF_HIDDEN RDCF_SYSTEM
Possible return values are as follows:
return value meaning
----------------------- -------------------------------------
0 successful operation
RDCF_DIRECTORY_CONFLICT file name conflicts with subdirectory
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_FORMAT_ERROR corrupt file allocation table
RDCF_FILE_NOT_FOUND file not found
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
If RDCF is compiled as a read-only file system, this function is not defined.
8.2. rdcf_close() - Close a File
--------------------------------
If a file has been written or otherwise modified, you must close it in order to
update its directory entry. Here is the appropriate function call:
e = rdcf_close(fcb);
struct rdcf *fcb; pointer to open file control block
int e; 0 for a successful operation, or a negative error
code
The file control block must have been successfully opened by rdcf_open().
If the file has been modified, its date and time will be set to the value
returned by rdcf_get_date_and_time().
If a file has not been written or otherwise modified, there is no need to close
it, and this function will do nothing to it. If RDCF is compiled as a read-only
file system, this function is not even defined.
Possible return values are as follows:
return value meaning
----------------- --------------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
8.3. rdcf_date_and_time() - Change Date and Time
------------------------------------------------
The following function call changes the date and time of a file, volume name
or subdirectory:
e = rdcf_date_and_time(fcb, filespec, t);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
struct rdcf_date_and_time *t; pointer to block containing desired
date and time
int e; 0 if operation was successful,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
drive B:, etc. In other cases, the file specification for a volume name is
the empty string ("").
When the time and date of a subdirectory are changed, the time and date of its
special subdirectories "." and ".." are also changed.
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_FORMAT_ERROR corrupt file allocation table
RDCF_FILE_NOT_FOUND file not found
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
If RDCF is compiled as a read-only file system, this function is not defined.
8.4. rdcf_delete() - Delete a File, Volume Name or Subdirectory
----------------------------------------------------------------
The following function call deletes a file, volume name or subdirectory:
e = rdcf_delete(fcb, filespec);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
int e; 0 if file was successfully opened,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the file specification for a volume name
consists of a drive specification alone, e.g., "A:" for drive A:, "B:" for
drive B:, etc. In other cases, the file specification for a volume name is
the empty string ("").
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------
0 successful operation
RDCF_ACCESS_DENIED attempt to delete a read-only file or a
subdirectory that is not empty
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_NOT_FOUND file, volume name or directory not found
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
If RDCF is compiled as a read-only file system, this function is not defined.
8.5. rdcf_directory() - Create a New Subdirectory
-------------------------------------------------
The following function call creates a new subdirectory:
e = rdcf_directory(fcb, filespec);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
int e; 0 if operation was successful,
or negative error code
The new directory, and its special subdirectories "." and "..", will bear the
current date and time as determined by a call on rdcf_get_date_and_time().
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------
0 successful operation
RDCF_DIRECTORY_CONFLICT name conflicts with file or subdirectory
RDCF_DIRECTORY_FULL insufficient directory or data space
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
If RDCF is compiled as a read-only file system, this function is not defined.
8.6. rdcf_format() - Format a Disk
----------------------------------
Formatting a disk usually involves two operations, both of which are performed
by most DOS formatting utilities for diskettes.
The first operation, called physical formatting, divides the tracks up into
sectors and writes the necessary sector numbers into them. The sectors are
filled with meaningless bytes. RDCF has no provision for physical formatting
because the procedure is highly hardware-dependent.
The second operation, called logical formatting, writes the required
information into the bootstrap sector, the file allocation table, and the root
directory. RDCF performs logical formatting with the following function call:
e = rdcf_format(fcb, spec, format);
struct rdcf *fcb; pointer to file control block
char *spec; drive specification ("A:", "B:", etc.),
omitted if RDCF_MULTIPLE_DRIVE is undefined
struct rdcf_format *format; pointer to descriptor block for desired
format
int e; 0 if operation was successful,
or negative error code
The format parameter has any of four values, depending on the type of disk
being formatted:
value of format physical size density capacity
----------------- ------------- ------- --------
&rdcf_format_360 5-1/4 inch double 360K
&rdcf_format_720 3-1/2 inch double 720K
&rdcf_format_1200 5-1/4 inch high 1.2M
&rdcf_format_1440 3-1/2 inch high 1.44M
Logical formatting deletes all files, subdirectories and the volume name. Some
of this information can be reconstructed by rdcf_recover() or by special
recovery programs if it has not been overwritten. However, all the information
becomes inaccessible through normal DOS and RDCF calls. The disk also becomes
unbootable and cannot be made bootable with the DOS SYS utility.
This function is especially useful if the data storage device is not a
DOS-compatible disk. You can use it to format a RAM disk, a portion of a hard
disk, or even a file and use it as though it were a disk. The function
(*drive_access)() usually needs to be modified, but no other changes are
required.
If you want to use a nonstandard format, you can make up your own format
descriptor block. Here is what is in it:
byte contents
---- ------------------------------------------------------
0 LS byte of number of bytes per sector
1 MS byte of number of bytes per sector
2 number of sectors per data cluster
3 1
4 0
5 number of file allocation tables
6 LS byte of number of root directory entries
7 MS byte of number of root directory entries
8 LS byte of total number of sectors
9 MS byte of total number of sectors
10 unused
11 LS byte of number of sectors per file allocation table
12 MS byte of number of sectors per file allocation table
13 LS byte of number of sectors per track
14 MS byte of number of sectors per track
15 LS byte of number of sides
16 MS byte of number of sides
17 unused
18 unused
NOTICE that some two-byte parameters are not aligned on even boundaries.
Of course, if you format a disk in a nonstandard manner, DOS may not be able to
read it. There are a number of limitations on the parameters to guarantee a
self-consistent format that RDCF can use:
(1) None of the parameters can be zero (although the MS byte of a two-byte
parameter can be zero).
(2) The sector size must be a multiple of 32; but if RDCF_SECTOR_SIZE is
defined, RDCF ignores this field.
(3) The number of root directory entries must be a multiple of the number
of entries in a sector. Each entry occupies 32 bytes, so if 512-byte
sectors are used, the number of entries per sector is 16.
(4) The disk contains the following areas, which must add up to the
specified total number of sectors:
(a) one bootstrap sector,
(b) the specified number of file allocation tables, each containing
the specified number of sectors,
(c) the root directory, and
(d) the data sectors.
(5) The number of data sectors must be a multiple of the number of sectors
per data cluster. Their quotient is the number of data clusters.
(6) The number of data clusters must not exceed 65,517.
(6) If the number of data clusters is 4077 or less, then each file
allocation table must contain at least 3 bytes plus one and one-half
bytes for each data cluster. Otherwise, each file allocation table
must contain at least 4 bytes plus 2 bytes for each data cluster.
Parameters described as "unused" are not used by RDCF, although they may have
meanings on a DOS diskette. The rdcf_format() function makes only a
perfunctory consistency check on the parameters.
RDCF does not use the number of sectors per track or the number of sides, but
the function (*drive_access)() may need them.
Possible return values are as follows:
return value meaning
------------------------ -----------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR improper format control block
RDCF_DRIVE_ERROR error in writing disk
RDCF_INVALID_SPEC invalid drive specification
If RDCF is compiled as a read-only file system, this function is not defined.
8.7. rdcf_free_space() - Get Disk Free Space
---------------------------------------------
The following function call returns the number of bytes of free space on a
disk:
n = rdcf_free_space(fcb, char *spec);
struct rdcf *fcb; pointer to file control block
char *spec; drive specification ("A:", "B:", etc.),
omitted if RDCF_MULTIPLE_DRIVE is undefined
long n; number of free bytes, or a
negative error code
If the operation is successful, the number of free bytes is also left in the
member fcb->file.size.
In the absence of drive errors, the number of free bytes returned by this
function is the maximum number of bytes that can be added to an existing file
that fills a whole number of data clusters. The number of additional bytes
that can be written to existing files may be larger, because each file may
have some empty space in its last cluster that is not counted as free by this
function.
The number of bytes that can be written to a newly created file is also the
same as the value returned by this function, except in one peculiar case. If
a new file is added to a subdirectory, it may be necessary to add a cluster to
the subdirectory to accommodate the new file entry. This cluster is not
available for file data.
Possible error codes are as follows:
return value meaning
---------------------- ---------------------------
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_INVALID_SPEC invalid drive specification
8.8. rdcf_get_file_information() - Get a Directory Entry
--------------------------------------------------------
The following function reads a directory entry:
e = rdcf_get_file_information(fcb, specs, index);
struct rdcf *fcb; pointer to file control block
char *filespec; directory specification string, with
terminating \0
unsigned index; index of desired entry (0 = first entry,
1 = second entry, etc.)
int e; 0 if entry was successfully read,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
root directory consists of a drive specification alone, such as "D:".
Otherwise, the empty string ("") represents the root directory.
If the operation is successful, useful information about the file, volume name
or subdirectory will be found in the file information block fcb->file.
If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
file, volume name or subdirectory. The first character in the name is invalid
but other information is valid and reflects the status of the file, volume
name or subdirectory before it was deleted.
If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
RDCF_DIRECTORY bit will be set in the attribute byte.
Entries 0 and 1 in a subdirectory represent the special directory entries named
"." and "..". RDCF makes no use of these special entries, but it faithfully
emulates this DOS feature.
The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
beyond the end of the directory area, or if the entry lies inside this area but
has never been used since the directory was created. In either case, the entry
is invalid and there are no valid entries with any higher index value.
Even if the entry is valid and represents a file, the file control block may
not be used to read, write or otherwise manipulate the file until it is
successfully opened by rdcf_open().
If you call this function repeatedly to scan the directory, you should
probably use some kind of caching. Otherwise, both the bootstrap block and the
directory will be read from disk with each function call. Even without
caching, this function produced acceptable results when used to display a
directory listing of a floppy diskette, although the process was a little
slower than most people would prefer.
The companion function rdcf_next_file_information(), which is described below,
can also be called to obtain the following entry without repeating the entire
directory search.
Possible return values are as follows:
return value meaning
---------------------- ------------------------------
0 successful operation
RDCF_DIRECTORY_FULL index is past end of directory
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_FILE_NOT_FOUND entry represents deleted file
RDCF_INVALID_SPEC invalid drive specification
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
8.9. rdcf_get_volume() - Get Volume Name
----------------------------------------
The following function call scans the root directory for the volume name, if
any:
e = rdcf_get_volume(fcb, char *spec);
struct rdcf *fcb; pointer to file control block
char *spec; drive specification ("A:", "B:", etc.),
omitted if RDCF_MULTIPLE_DRIVE is undefined
int e; 0 if volume name was successfully read,
or negative error code
If the operation is successful, information regarding the volume name is left
in the file information block fcb->file.
Possible return values are as follows:
return value meaning
---------------------- ------------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_FILE_NOT_FOUND disk has no volume name
RDCF_INVALID_SPEC invalid drive specification
8.10. rdcf_next_file_information() - Get Next Directory Entry
-------------------------------------------------------------
The following function reads the next directory entry after the one read by the
most recent call on rdcf_get_file_information() or rdcf_next_file_information()
using the same file control block:
e = rdcf_next_file_information(fcb);
struct rdcf *fcb; pointer to the same file control block used
by a previous call on this function or
rdcf_get_file_information()
int e; 0 if entry was successfully read,
or negative error code
The file control block and scratch buffer must be the same ones used by the
preceding call on rdcf_get_file_information() or this function, and the
directory structure on the disk must not have changed. The preceding call must
not have returned RDCF_DIRECTORY_FULL. This function uses information left in
the file control block to find the next directory entry without rescanning the
directory.
If the operation is successful, useful information about the file, volume name
or subdirectory will be found in the file information block fcb->file.
If the return value is RDCF_FILE_NOT_FOUND, the entry represents an erased
file, volume name or subdirectory. The first character in the name is invalid
but other information is valid and reflects the status of the file, volume
name or subdirectory before it was deleted.
If the entry represents a volume name or subdirectory, the RDCF_VOLUME or
RDCF_DIRECTORY bit will be set in the attribute byte.
Entries 0 and 1 in a subdirectory represent the special directory entries named
"." and "..". RDCF makes no use of these special entries, but it faithfully
emulates this DOS quirk.
The value RDCF_DIRECTORY_FULL is returned if the index would put the entry
beyond the end of the directory area, or if the entry lies inside this area but
has never been used since the directory was created. In either case, the entry
is invalid and there are no valid entries with any higher index value.
Even if the entry is valid and represents a file, the file control block may
not be used to read, write or otherwise manipulate the file until it is
successfully opened by rdcf_open().
Possible return values are as follows:
return value meaning
---------------------- ------------------------------
0 successful operation
RDCF_DIRECTORY_FULL index is past end of directory
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_FILE_NOT_FOUND entry represents deleted file
8.11. rdcf_match() - Match Name and Extension
---------------------------------------------
The following function determines whether a DOS file name and extension match
a DOS pattern, which may include the special characters ? and *:
match = rdcf_match(name_extension, pattern);
char *name_extension; DOS name and extension, with separating . and
terminating \0
char *pattern; DOS name and extension, with separating . and
terminating \0, possibly including the special
characters ? and *
int match; true (nonzero) if the name and extension match
the pattern; false (zero) otherwise
The function follows all the usual DOS quirks. Small letters are converted to
capital letters before comparison. The name is truncated to eight characters,
and the extension is truncated to three characters.
The function does not check the validity of the name and extension or the
pattern.
8.12. rdcf_move() - Move a File or Subdirectory
-----------------------------------------------
The following function call moves a file or subdirectory from one directory to
another ON THE SAME DRIVE:
e = rdcf_move(fcb, old_filespec, new_filespec);
struct rdcf *fcb; pointer to file control block
char *old_filespec; old file specification string, with
terminating \0
char *new_filespec; new file specification, with
terminating \0
int e; 0 if file was successfully opened,
or negative error code
The new file specification may not begin with a drive specification, even if
RDCF_MULTIPLE_DRIVE is defined. However, it may, and often does, begin with a
directory path.
The file name and extension in the new file specification need not be the same
as those in the old file specification. The file or subdirectory can be
renamed as it is moved.
The file or directory entry in the old position will be marked as deleted.
You may use this function to move a subdirectory, but you must be careful not
to corrupt the tree structure by moving a subdirectory into itself or one of
its subdirectories. RDCF will not protect you from such folly.
Possible return values are as follows:
return value meaning
----------------------- ------------------------------------------
0 successful operation
RDCF_DIRECTORY_FULL insufficient directory space for new entry
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_NOT_FOUND file not found
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_RENAMING_ERROR new file specification is already in use
If RDCF is compiled as a read-only file system, this function is not defined.
8.13. rdcf_open() - Open a File
-------------------------------
The following function call opens a file:
e = rdcf_open(fcb, filespec, mode);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
unsigned mode; file mode (not used if RDCF is read-only)
int e; 0 if file was successfully opened,
or negative error code
If the file is successfully opened, the file pointer is set to the beginning
of the file and the file control block is initialized for use by other RDCF
operations on the file. The file information block fcb->file then contains
meaningful information about the file.
The mode may be as follows:
mode operation
--------------- ------------------------------------------------
RDCF_CREATE create file for writing, deleting the file if it
already exists
RDCF_READ open file for reading only
RDCF_READ_WRITE open file for reading and writing
In read-only file systems, RDCF_READ is the only mode permitted, so the mode
parameter is absent.
You may wish to open a file in the RDCF_READ mode merely to obtain information
from its file control block. Then you can abandon or re-use the file control
block; there is no need to close the file.
You can emulate the full panoply of DOS open() modes by calling this function
more than once.
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------------
0 successful operation
RDCF_ACCESS_DENIED attempt to write a read-only file
RDCF_DIRECTORY_CONFLICT file name conflicts with subdirectory
RDCF_DIRECTORY_FULL insufficient directory space to create a file
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_NOT_FOUND file not found in RDCF_READ or RDCF_READ_WRITE
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_MODE_ERROR invalid mode
8.14. rdcf_read() - Read from a File
------------------------------------
The following function call reads a block of bytes from an open file:
n = rdcf_read(fcb, buffer, count);
struct rdcf *fcb; pointer to open file control block
void *buffer; memory buffer to receive data
int count; number of bytes to be read
int n; number of bytes actually read, or a negative
error code
The file control block must have been successfully opened in mode RDCF_READ or
RDCF_READ_WRITE by rdcf_open().
Reading starts at the current file pointer position. If the operation is
successful, the file pointer is advanced to the byte immediately following the
last byte read.
The return value is the number of bytes actually read. If this nonnegative but
less than the count, the end of the file was encountered.
Errors are indicated by the following negative return values:
return value meaning
---------------------- ------------------------------------------
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_FILE_FORMAT_ERROR corrupt file allocation table
RDCF_MODE_ERROR file mode not RDCF_READ or RDCF_READ_WRITE
8.15. rdcf_recover() - Recover Erased Data
------------------------------------------
The following function call creates a new file and puts all unused data
clusters into it:
e = rdcf_recover(fcb, filespec);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
int e; 0 if file was successfully opened,
or negative error code
When a file is deleted by DOS or RDCF, the information contained in the file is
not actually erased. The data clusters containing the information are merely
marked as unused. Until these clusters are actually used for other files, the
information is still there, and can be recovered and assembled into a single
file by calling this function.
The file specifications must be for a new file. If you try to use an existing
file, this function will return the error code RDCF_ACCESS_DENIED.
If you specify a file in a subdirectory, it will NOT be lengthened to
accommodate the new file, as it would be when you call rdcf_open(). That would
destroy information and partially defeat the purpose of this function. If
there is no empty space in the subdirectory, this function will return the
error code RDCF_DIRECTORY_FULL.
If this function is successfully called, the new file will contain all the data
in all unused clusters on the specified drive. Of course, the unused clusters
will no longer be unused, and the drive will then be completely full. If you
want to edit the information, you may have to copy the file to another drive
that has room for the backup and scratch files that most text editors require.
Some kind of editing is usually required because the new file will typically
contain information from a number of old deleted files or subdirectories, and
the information will be slightly mixed up if the old files were fragmented.
Possible return values are as follows:
return value meaning
----------------------- -----------------------------------
0 successful operation
RDCF_ACCESS_DENIED attempt to use an existing file
RDCF_DIRECTORY_FULL insufficient directory space
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
If RDCF is compiled as a read-only file system, this function is not defined.
8.16. rdcf_rename() - Rename a File or Subdirectory
---------------------------------------------------
The following function call changes the name and/or extension of a file or
subdirectory:
e = rdcf_rename(fcb, old_filespec, new_filespec);
struct rdcf *fcb; pointer to file control block
char *old_filespec; old file specification string, with
terminating \0
char *new_filespec; new name and extension, with
terminating \0
int e; 0 if file was successfully opened,
or negative error code
The new file specification may not begin with a drive specification or
directory path.
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------
0 successful operation
RDCF_ACCESS_DENIED attempt to rename a hidden or system file
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_NOT_FOUND file not found
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_RENAMING_ERROR new file specification is already in use
If RDCF is compiled as a read-only file system, this function is not defined.
8.17. rdcf_seek() - Move a File Pointer
---------------------------------------
The following function call moves a file pointer:
e = rdcf_seek(fcb, offset);
struct rdcf *fcb; pointer to open file control block
unsigned long offset; desired file pointer offset,
relative to beginning of file
int e; 0 for a successful operation,
or a negative error code
The file control block must have been successfully opened by rdcf_open() in any
mode.
If the operation is successful, the function returns zero. The next call on
rdcf_read() or rcdf_write() will start at the specified position, relative to
the beginning of the file.
The file control block entry fcb->position or fcb->file.size can be used to
convert an offset from the file pointer or end of file to an offset from the
beginning of the file.
A file cannot be lengthened by moving the file pointer past the end of the
file. To lengthen a file, you must move the file pointer to the end of the
file and then write enough data to it to make it the desired length.
Possible return values are as follows:
return value meaning
----------------- -------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_SEEK_OUT_OF_RANGE offset exceeds file size
8.18. rdcf_set_file_information() - Set File Information
--------------------------------------------------------
The following function writes new information into a directory entry:
e = rdcf_set_file_information(fcb, filespec, index, p);
struct rdcf *fcb; pointer to file control block
char *filespec; directory specification string, with
terminating \0
unsigned index; index of desired entry (0 = first entry,
1 = second entry, etc.)
struct rdcf_file_information *p;
pointer to block with new directory
information
int e; 0 if entry was successfully written,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
root directory consists of a drive specification alone, such as "A:".
Otherwise, the empty string ("") represents the root directory.
This function takes a block of information, converts it to DOS directory
format, and writes it into the specified directory entry. The block of
information is usually supplied by rdcf_get_file_information. This function is
used almost exclusively for special disk utilities.
If p->spec[0] is zero, the entire entry will be cleared to zeros.
This function will not lengthen a subdirectory if the index is past its current
end.
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------
0 successful operation
RDCF_DIRECTORY_FULL index is past end of directory
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
If RDCF is compiled as a read-only file system, this function is not defined.
8.19. rdcf_set_volume() - Write Volume Name
-------------------------------------------
The following function writes a new volume name:
e = rdcf_set_volume(fcb, drive_name);
struct rdcf *fcb; pointer to file control block
char *drive_name; string of form "d:name" that specifies
drive and name, with terminating \0
int e; 0 if name was successfully written,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the string drive_name begins with a drive
specification (a drive letter, followed by a colon). Otherwise, it contains
only the volume name. In any case, it is terminated by \0.
If the volume name is less than 11 characters long, RDCF will pad it with
blanks at the end before writing it to the disk.
Notice that the volume name may contain small letters, which are NOT converted
to capital letters by RDCF. Volume names in DOS are case-sensitive. RDCF will
reject the volume name and return RDCF_INVALID_SPEC if the first character of
the name is 0xE5, which indicates a deleted file or volume name.
If there is already a volume name on the drive, it is replaced by the specified
one.
The new volume name will bear the current date and time as determined by a call
on rdcf_get_date_and_time().
return value meaning
---------------------- -----------------------------------
0 successful operation
RDCF_DIRECTORY_FULL insufficient directory space
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading disk
RDCF_INVALID_SPEC invalid drive specification or name
If RDCF is compiled as a read-only file system, this function is not defined.
8.20. rdcf_sort_directory() - Sort a Directory
----------------------------------------------
The following function call sorts a directory:
e = rdcf_sort_directory(f, filespec, mode);
struct rdcf *fcb; pointer to file control block
char *filespec; directory specification string, with
terminating \0
int mode; code to indicate the kind of sort
int e; 0 if directory was successfully sorted,
or negative error code
If RDCF_MULTIPLE_DRIVE is defined, the directory specification string for the
root directory consists of a drive specification alone, such as "A:".
Otherwise, the empty string ("") represents the root directory.
The sorting mode may be any ONE of the following:
mode manner of sort
------------------- ---------------------------------------------
RDCF_EXTENSION_NAME sort by extension, then among files that have
the same extension, sort by name
RDCF_NAME_EXTENSION sort by name, then among files that have
the same name, sort by extension
RDCF_DATE_TIME sort by date and time (earlier files first)
RDCF_SIZE sort by size (smallest files first)
The modifier RDCF_REVERSE may be added to any of these modes to sort in the
opposite order. For example, RDCF_SIZE+RDCF_REVERSE sorts the files by size,
but it puts the largest files first.
Actually, before the function sorts the directory entries, it first divides
them into five groups and arranges them in the following order:
(1) The two system files at the beginning of the root directory and the
two special files "." and ".." at the beginning of a subdirectory are
always left where they are.
(2) The volume label, if any, is put next.
(3) The subdirectory entries, if any, are sorted and put next.
(4) The file entries are sorted and put next.
(5) The entries for deleted files, volume labels and subdirectories, if
any, are sorted and put last.
Within each category, if two entries are identical according to the sorting
criterion, their relative position is left unchanged.
Some kind of caching is strongly recommended when using this function. The
sorting algorithm is rather primitive one called a "bubble sort", so it may
take a noticeable amount of time to sort a long directory, even with caching.
Possible return values are as follows:
return value meaning
----------------------- ----------------------------------------
0 successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
If RDCF is compiled as a read-only file system, this function is not defined.
8.21. rdcf_undelete() - Restore a Deleted File
----------------------------------------------
When you delete a file, with either DOS or RDCF, the information in the file is
not erased, although it may become rather difficult to find.
The following function call restores the original contents of a deleted file,
to the extent possible:
e = rdcf_undelete(fcb, filespec);
struct rdcf *fcb; pointer to file control block
char *filespec; file specification string, with
terminating \0
int e; 0 if file was even partially recovered,
or negative error code
The function will attempt to restore as much of the file as possible. If only
part of the file can be restored, the value in fcb->position will indicate how
much of the file was NOT restored. If the entire file was restored, this entry
will be zero. If nothing can be restored because the first data cluster of the
file is in use by another file, the function will return
RDCF_UNRECOVERABLE_FILE.
Even an apparently successful restoration may not restore the original file
contents. For example, if another file was written over the original file
contents and then deleted, RDCF may have no way of knowing that the file
contents have changed.
Complete restoration of a file can be assured if the original file was
unfragmented before it was deleted and nothing has been written to the disk
after it was deleted.
Possible return values are as follows:
return value meaning
----------------------- ---------------------------------------
0 fully or partially successful operation
RDCF_DIRECTORY_FULL index is past end of directory
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_NOT_FOUND entry did not represent a deleted file
RDCF_INVALID_DIRECTORY nonexistent subdirectory in path
RDCF_INVALID_SPEC invalid drive or file specification
RDCF_UNRECOVERABLE_FILE none of the file can be restored
If RDCF is compiled as a read-only file system, this function is not defined.
8.22. rdcf_wipe_disk() - Wipe Out Erased Data
---------------------------------------------
The following function call writes nonsense over all unused clusters of the
specified drive:
e = rdcf_wipe_disk(fcb, spec);
struct rdcf *fcb; pointer to file control block
char *spec; drive specification ("A:", "B:", etc.),
omitted if RDCF_MULTIPLE_DRIVE is undefined
int e; 0 if operation was successful,
or negative error code
When a file is deleted by DOS or RDCF, the information contained in the file is
not actually erased. The data clusters containing the information are merely
marked as unused. Until these clusters are actually used for other files, the
information is still there, and can often be recovered by calling
rdcf_undelete() or rdcf_recover() or by using a file recovery utility.
For security reasons, you may want to make sure your erased files are really
erased. This function does that by writing nonsense into every cluster marked
as unused.
The information is not completely destroyed. It may be possible to read some of
it by subjecting the disk to a special analysis in a laboratory, but it cannot
be read by an ordinary file recovery utility.
Even erasing every unused cluster won't necessarily remove all the information
from erased files. There may be unused sectors at the ends of files that are
not erased. The last cluster of such a file is not marked as unused, because
part of it is being used. But the part that is not being used may contain
information from an older file that did use the entire cluster.
Possible return values are as follows:
return value meaning
----------------------- ------------------------------------------
0 fully or partially successful operation
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_INVALID_SPEC invalid drive specification
If RDCF is compiled as a read-only file system, this function is not defined.
8.23. rdcf_write() - Write to a File
------------------------------------
The following function call writes a block of bytes to an open file:
n = rdcf_write(fcb, buffer, count);
struct rdcf *fcb; pointer to open file control block
void *buffer; memory buffer to supply data
int count; number of bytes to be written
int n; number of bytes actually written, or a negative
error code
The file control block must have been successfully opened in mode RDCF_CREATE
or RDCF_READ_WRITE by rdcf_open().
Writing starts at the current file pointer position. If the operation is
successful, the file pointer is advanced to the byte immediately following the
last byte written.
If necessary, the file is lengthened to accommodate the bytes being written.
The return value is the number of bytes actually written. If this is
nonnegative but less than the count, there was insufficient disk space to write
all the data.
Other errors are indicated by the following negative return values:
return value meaning
--------------------- --------------------------------------------
RDCF_DISK_FORMAT_ERROR disk improperly formatted
RDCF_DRIVE_ERROR error in reading or writing disk
RDCF_FILE_FORMAT_ERROR corrupt file allocation table
RDCF_MODE_ERROR file mode not RDCF_CREATE or RDCF_READ_WRITE
This function also sets an internal flag to indicate that the file has been
written, which causes RDCF to update the directory when the file is later
closed. If the count is zero, setting the flag is all it does.
If RDCF is compiled as a read-only file system, this function is not defined.
----------------end-of-author's-documentation---------------
Software Library Information:
This disk copy provided as a service of
Public (software) Library
We are not the authors of this program, nor are we associated
with the author in any way other than as a distributor of the
program in accordance with the author's terms of distribution.
Please direct shareware payments and specific questions about
this program to the author of the program, whose name appears
elsewhere in this documentation. If you have trouble getting
in touch with the author, we will do whatever we can to help
you with your questions. All programs have been tested and do
run. To report problems, please use the form that is in the
file PROBLEM.DOC on many of our disks or in other written for-
mat with screen printouts, if possible. PsL cannot debug pro-
programs over the telephone, though we can answer questions.
Disks in the PsL are updated monthly, so if you did not get
this disk directly from the PsL, you should be aware that the
files in this set may no longer be the current versions. Also,
if you got this disk from another vendor and are having prob-
lems, be aware that some files may have become corrupted or
lost by that vendor. Get a current, working disk from PsL.
For a copy of the latest monthly software library newsletter
and a list of the 4,000+ disks in the library, call or write
Public (software) Library
P.O.Box 35705
Houston, TX 77235-5705
Orders only:
1-800-2424-PSL
MC/Visa/AmEx/Discover
Outside of U.S. or in Texas
or for general information,
Call 1-713-524-6394